package com.ziytek.web.citizen.service.impl;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ziytek.web.citizen.configuration.db.DDS;
import com.ziytek.web.citizen.constant.DdsConstant;
import com.ziytek.web.citizen.constant.NumConstant;
import com.ziytek.web.citizen.constant.SettingConstant;
import com.ziytek.web.citizen.enums.ResponseEnum;
import com.ziytek.web.citizen.enums.SchmeEnum;
import com.ziytek.web.citizen.mapper.CapacitySchemeMapper;
import com.ziytek.web.citizen.model.bean.CapacityLevel;
import com.ziytek.web.citizen.model.bean.SchemeQueryResult;
import com.ziytek.web.citizen.model.req.CapacitySchemeAddReq;
import com.ziytek.web.citizen.model.req.CapacitySchemeModifyReq;
import com.ziytek.web.citizen.model.req.SchemeQueryReq;
import com.ziytek.web.citizen.model.rsp.SchemeQueryRsp;
import com.ziytek.web.citizen.pojo.basic.BasicCapacityScheme;
import com.ziytek.web.citizen.service.itf.CapacitySchemeService;
import com.ziytek.web.citizen.util.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * @author fenghx
 * @version 1.0
 * @className CapacitySchemeServiceImpl
 * Description:
 * @date 2024/3/25 11:34
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CapacitySchemeServiceImpl implements CapacitySchemeService {
    private final Gson gson;
    private final CapacitySchemeMapper capacitySchemeMapper;

    @Override
    @DDS(DdsConstant.DS_BASIC)
    public String schemeAdd(CapacitySchemeAddReq req, Long id, boolean addNew) {
        // 异常判断
        var code = errorCode(req);
        if (!SchmeEnum.SUCCESS.getCode().equals(code)) {
            return code;
        }

        var planNo = req.getPlanNo();
        var name = req.getPlanName();
        var time = req.getOperatorTime();
        var levelList = req.getLevelList();
        // 排序
        try {
            levelList.sort(Comparator.comparing(CapacityLevel::getOrder));
        } catch (Exception e) {
            levelList.sort(Comparator.comparing(CapacityLevel::getLevelStart));
            log.info("getOrder sort error:", e);
        }

        var sizeStart = NumConstant.INT_ZERO;
        var size = levelList.size();
        if (isNextError(sizeStart, size, levelList)) {
            return SchmeEnum.SET_LIST_DATA_ERROR_TWO.getCode();
        }

        if (addNew) {
            return schemeSave(name, planNo, time, levelList, req.getOperatorId());
        }

        id = id != null && id > NumConstant.LONG_ZERO ? id : NumConstant.LONG_LT_TEN;
        var scheme = capacitySchemeMapper.findFirstById(id);
        if (scheme == null || SettingConstant.IS_NORMAL != scheme.getIsDelete()) {
            scheme = capacitySchemeMapper.findFirstByPlanNoAndIsDeleteOrderByCreateTimeDesc(planNo, SettingConstant.IS_NORMAL);
        }

        if (scheme == null) {
            return SchmeEnum.OBJECT_NOT_EXIST.getCode();
        }

        // 不是新增方案，修改方案
        var oldScheme = capacitySchemeMapper.findFirstByPlanNameAndIsDeleteOrderByCreateTimeDesc(name, SettingConstant.IS_NORMAL);
        // 新增方案名称不能重复
        if (oldScheme != null && !oldScheme.getId().equals(scheme.getId())) {
            return SchmeEnum.UPDATE_NAME_ERROR.getCode();
        }

        var operatorTime = StringUtil.toLong(time);
        operatorTime = operatorTime <= NumConstant.INT_ZERO ? System.currentTimeMillis() : operatorTime;

        fillCapacityScheme(scheme, name, planNo, req.getOperatorId(), operatorTime, gson.toJson(req.getLevelList()));

        try {
            capacitySchemeMapper.schemeAllUpdate(scheme);
        } catch (Exception e) {
            log.error("工步方案新增异常:{},", req, e);
            return SchmeEnum.MODIFY_ERROR.getCode();
        }

        return SchmeEnum.SUCCESS.getCode();
    }

    @Override
    @DDS(DdsConstant.DS_BASIC)
    public String schemeModify(CapacitySchemeModifyReq req) {
        var idStr = req.getId();
        var id = StringUtil.toLong(idStr);
        var scheme = capacitySchemeMapper.findFirstById(id);
        if (scheme == null || SettingConstant.IS_NORMAL != scheme.getIsDelete()) {
            // 工步方案不存在
            return SchmeEnum.OBJECT_NOT_EXIST.getCode();
        }

        // 新增新配置
        var add = new CapacitySchemeAddReq();
        BeanUtils.copyProperties(req, add);
        return schemeAdd(add, id, false);
    }

    @Override
    @DDS(DdsConstant.DS_BASIC)
    public int schemeDel(String id) {
        if (StringUtil.isEmpty(id) || StringUtil.toLong(id) <= NumConstant.LONG_ZERO) {
            return NumConstant.INT_ZERO;
        }
        try {
            var capacityScheme = capacitySchemeMapper.findFirstById(StringUtil.toLong(id));
            var isNormal = capacityScheme != null && SettingConstant.IS_NORMAL == capacityScheme.getIsDelete();
            if (isNormal) {
                capacityScheme.setIsDelete(SettingConstant.IS_DELETE);
                capacityScheme.setUpdateTime(System.currentTimeMillis());
                capacitySchemeMapper.schemeUpdate(SettingConstant.IS_DELETE, System.currentTimeMillis(), capacityScheme.getId());
            }
        } catch (Exception e) {
            log.error("删除分容方案失败:{},", id, e);
            return NumConstant.INT_ZERO;
        }
        return NumConstant.INT_ONE;
    }

    @Override
    @DDS(DdsConstant.DS_BASIC)
    public SchemeQueryRsp schemeQuery(SchemeQueryReq req) {
        var response = new SchemeQueryRsp();
        response.setRetCode(ResponseEnum.SUCCESS.getCode());
        response.setRetMsg(ResponseEnum.SUCCESS.getDesc());
        List<BasicCapacityScheme> list = (StringUtil.isEmpty(req.getId()) || StringUtil.toLong(req.getId()) <= NumConstant.LONG_ZERO) ? capacitySchemeMapper.findByIsDeleteOrderByCreateTimeAsc(SettingConstant.IS_NORMAL) : null;
        if (CollectionUtils.isEmpty(list)) {
            BasicCapacityScheme stepSettingsTable = capacitySchemeMapper.findFirstByIdAndIsDelete(StringUtil.toLong(req.getId()), SettingConstant.IS_NORMAL);
            if (stepSettingsTable == null) {
                return response;
            }

            list = new ArrayList<>();
            list.add(stepSettingsTable);
        }

        List<SchemeQueryResult> results = new ArrayList<>();
        for (var sp : list) {
            var result = new SchemeQueryResult();
            BeanUtils.copyProperties(sp, result);
            result.setId(String.valueOf(sp.getId()));
            result.setLevelList(gson.fromJson(sp.getSchemes(), new TypeToken<List<CapacityLevel>>() {
            }.getType()));
            result.getLevelList().sort(Comparator.comparing(CapacityLevel::getLevelStart));
            results.add(result);
        }

        response.setData(results);
        return response;
    }


    private void fillCapacityScheme(BasicCapacityScheme scheme, String name, String planNo, String operatorId,
                                    long operatorTime, String schemes) {
        scheme.setPlanName(name);
        scheme.setPlanNo(planNo);
        scheme.setOperatorId(operatorId);
        scheme.setOperatorTime(operatorTime);
        // 启用
        scheme.setIsDelete(SettingConstant.IS_NORMAL);
        scheme.setUpdateTime(System.currentTimeMillis());
        scheme.setSchemes(schemes);
    }

    private String errorCode(CapacitySchemeAddReq req) {
        if (req == null) {
            return ResponseEnum.PARAMETER_ERROR.getCode();
        }

        String planNo = req.getPlanNo();
        String name = req.getPlanName();
        name = StringUtil.isEmpty(name) ? null : name.trim();
        List<CapacityLevel> levelList = req.getLevelList();
        if (StringUtil.hasOneEmpty(name, planNo)) {
            // 保护参数设置不正确
            return SchmeEnum.NAME_NOT_EXIST.getCode();
        }
        if (CollectionUtils.isEmpty(levelList)) {
            // 工步设置不能为空
            return SchmeEnum.SET_LIST_EMPTY.getCode();
        }
        if (levelList.size() > NumConstant.INT_ONE_HUNDRED) {
            // 分容等级设置数量上限不能大于100
            return SchmeEnum.LIST_COUNT_OUT.getCode();
        }

        boolean isError = levelList.stream().anyMatch(c -> (c.getLevelStart() == null || c.getLevelEnd() == null || c.getLevelStart() > c.getLevelEnd()));
        if (isError) {
            // 工步设置异常
            return SchmeEnum.SET_LIST_DATA_ERROR.getCode();
        }

        return SchmeEnum.SUCCESS.getCode();
    }

    private boolean isNextError(int sizeStart, int size, List<CapacityLevel> levelList) {
        for (int i = sizeStart; i < size; i++) {
            CapacityLevel capacityLevel = levelList.get(i);
            CapacityLevel capacityLevelNext = null;
            if (i + NumConstant.INT_ONE <= size - NumConstant.INT_ONE) {
                capacityLevelNext = levelList.get(i + NumConstant.INT_ONE);
            }
            if (capacityLevel != null && capacityLevelNext != null && capacityLevel.getLevelEnd() >= capacityLevelNext.getLevelStart()) {
                // 工步设置异常
                return true;
            }
        }

        return false;
    }

    private String schemeSave(String name, String planNo, String time, List<CapacityLevel> levelList, String operatorId) {

        BasicCapacityScheme nameScheme = capacitySchemeMapper.findFirstByPlanNameAndIsDeleteOrderByCreateTimeDesc(name, SettingConstant.IS_NORMAL);
        BasicCapacityScheme planNoScheme = capacitySchemeMapper.findFirstByPlanNoAndIsDeleteOrderByCreateTimeDesc(planNo, SettingConstant.IS_NORMAL);

        // 新增方案名称不能重复
        if (nameScheme != null) {
            return SchmeEnum.UPDATE_NAME_ERROR.getCode();
        }
        // 新增方案名称不能重复
        if (planNoScheme != null) {
            return SchmeEnum.UPDATE_NO_ERROR.getCode();
        }

        BasicCapacityScheme scheme = new BasicCapacityScheme();

        scheme.setCreateTime(System.currentTimeMillis());

        Long newId = capacitySchemeMapper.queryMaxId();
        scheme.setId(newId == null ? NumConstant.LONG_ONE : newId);

        try {
            long operatorTime = StringUtil.toLong(time);
            fillCapacityScheme(scheme, name, planNo, operatorId, operatorTime, gson.toJson(levelList));
            capacitySchemeMapper.schemeSave(scheme);
        } catch (Exception e) {
            log.error("工步方案新增异常:{},", scheme, e);
            return SchmeEnum.ADD_ERROR.getCode();
        }

        return SchmeEnum.SUCCESS.getCode();

    }
}
